package gps.methods;

import gps.Node;
import gps.SolverMethod;
import gps_api.State;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public abstract class BaseMethod implements SolverMethod{
	protected LinkedList<Node> openedNodes;
	protected List<Node> closedNodes;
	protected Node lastNode;
	protected Integer maxLevel;
	protected boolean lookCloseList=false;
	protected boolean lookOpenList=false;
	
	@Override
	public Node getNextNode() {
		lastNode= openedNodes.removeFirst();
		closedNodes.add(lastNode);
		setMaxlevel();
		
		return lastNode;
	}

	@Override
	public boolean hasEqualAncestor(State state) {	
		if(lookCloseList){
			return isInClosedList(state);
		}else{
			return lastNode.hasEqualAncestor(state);
		}		
	}

	@Override
	public void initMethod(State state) {
		openedNodes= new LinkedList<Node>();
		closedNodes= new ArrayList<Node>();
		openedNodes.add(new BaseNode(state));
		this.maxLevel=0;
	}

	@Override
	public boolean isEmptyOpenNodes() {
		return openedNodes.isEmpty();
	}

	@Override
	public void printSolution() {
		lastNode.printSolution();
	}

	
	@Override
	public boolean isInClosedList(State state){
		boolean ans=false;
		
		for (Node node : closedNodes) {
			if(node.getState().equals(state)){
				ans=true;
				break;
			}
		}
		
		return ans;
	}
	
	@Override
	public boolean isInOpenedList(Node newNode){
		boolean ans= false;
		int i=0;
		
		if(!lookOpenList){
			return false;
		}
		
		for (Node node : openedNodes) {
			if(node.getState().equals(newNode.getState())){
				if(node.getCost()>newNode.getCost()){
					openedNodes.remove(i);
				}else{
					ans=true;
				}
				break;
			}
			i++;
		}
		
		return ans;
	}
	
	

	
	@Override
	public void filterRepeatNodes(List<Node> nodes){
		
	}
	
	@Override
	public Integer getMaxLevel(){
		return maxLevel;
	
	}
	
	@Override
	public Integer getOpenListSize(){
		return openedNodes.size();	
	}

	@Override
	public Integer getCloseListSize(){
		return closedNodes.size();
		
	}
	
	public void setLookCloseList(boolean lookCloseList) {
		this.lookCloseList = lookCloseList;
	}

	public void setLookOpenList(boolean lookOpenList) {
		this.lookOpenList = lookOpenList;
	}

	protected void setMaxlevel(){
		if(lastNode.getLevel()> maxLevel){
			maxLevel= lastNode.getLevel();
		}
	}
}
